<?php

namespace app\common\model;
use app\api\model\DeveloperException;
use app\api\model\ServerException;
use app\api\model\TokenException;
use app\api\model\UserException;
use app\common\logic\RedisLock;
use think\facade\Cache;
use think\facade\Db;

class Order extends Base
{
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = true;

    /**
     * 订单支付信息
     * @param $user
     * @param $order_sn
     * @param $pay_type
     * @param $source
     * @return array
     * @throws DeveloperException
     * @throws ServerException
     * @throws UserException
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function payInfo($user,$order_sn,$pay_type,$source){

        try{
            $order_sn = reInject($order_sn);
            $pay_type = intval($pay_type);
            $source = intval($source);
            $lock_key = 'zfn_order_paying_'.$order_sn;

            RedisLock::checkDoingStrict($lock_key);

            $arr = [
                'type'=>0,
                'activity_type'=>0,
                'order_sn'=>$order_sn,
                'order_price'=>'0',
                'need_pay'=>1,
                'pay_type'=>$pay_type,
                'wechat'=>['none'=>'none'],
                'alipay'=>''
            ];

            $first = substr($order_sn,0,1);

            if($first=='P'){
                //父订单
                $order = Db::name('order_parent')
                    ->where('order_sn',$order_sn)
                    ->where('uid',$user['id'])
                    ->field('id,type,activity_type,uid,order_sn,uid,order_price,status,over_time')
                    ->find();

            }elseif ($first=='O'){
                //子订单支付
                $order = Db::name('order')
                    ->where('order_sn',$order_sn)
                    ->where('uid',$user['id'])
                    ->field('id,type,activity_type,merch_id,uid,order_sn,verify_type,is_expire,
                    expire_day,expire_time,expire_notice_time,uid,order_price,status,over_time')
                    ->find();
            }else{
                throw new UserException('无此订单');
            }

            //订单判断
            if(!$order){
                throw new UserException('无此订单或已删除');
            }

            //积分兑换只能积分
            if($order['activity_type']==2){
                $pay_type = 4;
            }else{
                if(!$pay_type){
                    throw new UserException('请选择支付方式');
                }
            }

            //返回信息
            $arr['type'] = $order['type'];
            $arr['activity_type'] = $order['activity_type'];
            $arr['order_price'] = $order['order_price'];

            if($order['status']==-1){
                throw new UserException('订单已取消');
            }

            if($order['status']!=0){
                throw new UserException('已支付订单请勿重复支付');
            }

            $time = time();

            if($order['over_time']<=$time){
                throw new UserException('订单支付已超时，请重新下单');
            }

            if($order['order_price']<0){
                throw new UserException('订单参数有误');
            }

            //限购判断
            if($first=='P'){
                $condition = [
                    ['order_parent_id','=',$order['id']],
                    ['all_buy','>',0]
                ];
            }else{
                $condition = [
                    ['order_id','=',$order['id']],
                    ['all_buy','>',0]
                ];
            }

            //限购
            $goods = Db::name('order_goods')
                ->where($condition)
                ->field('goods_id,num,unit,short_title,all_buy')
                ->select()
                ->toArray();
            $already = [];
            foreach ($goods as $go){

                if(in_array($go['goods_id'],$already)){
                    continue;
                }
                array_push($already,$go['goods_id']);

                $unit = $go['unit'];
                $user_all_buy = OrderNew::userAllBuy($user,$go['goods_id']);
                if($user_all_buy>=$go['all_buy']){
                    throw new UserException('商品【'.$go['short_title'].'】累计限购'.$go['all_buy'].$unit.'，您已购买'.$user_all_buy.$unit);
                }
                if(($user_all_buy+$go['num'])>$go['all_buy']){
                    throw new UserException('商品【'.$go['short_title'].'】累计限购'.$go['all_buy'].$unit.'，您已购买'.$user_all_buy.$unit.'，还可购买'.($go['all_buy']-$user_all_buy).$unit);
                }
            }

            //零元订单
            if($order['order_price']==0){
                //直接支付成功
                if($first=='P'){
                    self::parentPaySuccess('',$order,$pay_type,$order['order_price'],$order['order_price'],0);
                }else{
                    self::paySuccess('',$order,$pay_type,$order['order_price'],$order['order_price'],0);
                }
                $arr['need_pay'] = 0;

                RedisLock::removeDoing($lock_key);

                return $arr;
            }

            //选择支付方式
            switch ($pay_type){
                case 1:
                    if($order['activity_type']==2){
                        throw new UserException('微信支付不支持'.get_goods_activity_type(3,2).'订单');
                    }
                    //微信
                    if($source!=3){
                        //APP
                        $arr['wechat'] = (new Wechatpay(1))->appPay('购物支付',$order_sn,$order['order_price']);
                    }else{
                        //小程序
                        $arr['wechat'] = (new Wechatpay(2))->miniPay($user['mini_openid'],'购物支付',$order_sn,$order['order_price']);
                    }
                    break;
                case 2:
                    if($order['activity_type']==2){
                        throw new UserException('支付宝支付不支持'.get_goods_activity_type(3,2).'订单');
                    }
                    //支付宝
                    $alipay = new Alipay();
                    $res = $alipay->appPay('购物支付',$order_sn,$order['order_price']);
                    $arr['alipay'] = $res;
                    break;
                case 3:
                    //余额
                    if($order['activity_type']==2){
                        throw new UserException(config('self.user_money_title').'支付不支持'.get_goods_activity_type(3,2).'订单');
                    }

                    //余额支付
                    if($first=='P'){
                        $order_id = Db::name('order')
                            ->where('order_parent_id','=',$order['id'])
                            ->column('id');
                        $order_id = implode(',',$order_id);
                        $res = Finance::addDelUserMoney($user['id'],$order['order_price'],2,'支付购物订单'.$order_sn,4,$order_id);
                        self::parentPaySuccess('',$order,$pay_type,$order['order_price'],$order['order_price'],$res['data']);
                    }else{
                        $res = Finance::addDelUserMoney($user['id'],$order['order_price'],2,'支付购物订单'.$order_sn,4,$order['id']);
                        self::paySuccess('',$order,$pay_type,$order['order_price'],$order['order_price'],$res['data']);
                    }
                    $arr['need_pay'] = 0;
                    break;

                case 4:
                    //积分抵扣
                    if($order['activity_type']!=2){
                        throw new UserException(config('self.user_config_title').'支付只支持'.get_goods_activity_type(3,2).'订单');
                    }

                    if($first=='P'){
                        $order_id = Db::name('order')
                            ->where('order_parent_id','=',$order['id'])
                            ->column('id');
                        $order_id = implode(',',$order_id);
                        $res = Finance::addDelUserCoin($user['id'],$order['order_price'],2,'购物消费兑换使用'.$order_sn,4,$order_id);
                        self::parentPaySuccess('',$order,$pay_type,$order['order_price'],$order['order_price'],$res['data']);
                    }else{
                        $res = Finance::addDelUserCoin($user['id'],$order['order_price'],2,'购物消费兑换使用'.$order_sn,4,$order['id']);
                        self::paySuccess('',$order,$pay_type,$order['order_price'],$order['order_price'],$res['data']);
                    }
                    $arr['need_pay'] = 0;
                    break;
                default:
                    throw new DeveloperException('无此支付方式');
            }

            RedisLock::removeDoing($lock_key);
            return $arr;

        }catch (ServerException $exception)
        {
            RedisLock::removeDoing($lock_key);
            throw new ServerException($exception->getMessage());
        }
        catch (DeveloperException $exception)
        {
            RedisLock::removeDoing($lock_key);
            throw new DeveloperException($exception->getMessage());
        }
        catch (UserException $exception)
        {
            RedisLock::removeDoing($lock_key);
            throw new UserException($exception->getMessage());
        }
        catch (TokenException $exception)
        {
            RedisLock::removeDoing($lock_key);
            throw new TokenException($exception->getMessage());
        }
        catch (\Exception $exception)
        {
            RedisLock::removeDoing($lock_key);
            throw new UserException($exception->getMessage() . $exception->getFile() . $exception->getLine());
        }


    }

    /**
     * 父订单支付成功
     * @param $order_sn
     * @param $order
     * @param $pay_type
     * @param $order_price
     * @param $pay_price
     * @param string $transaction_id
     * @param string $pay_time
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function parentPaySuccess($order_sn,$order,$pay_type,$order_price,$pay_price,$transaction_id='',$pay_time='',$is_mini_pay=0){
        //传订单号代表需要重新查询和校验订单
        if(!empty($order_sn)){
            $order = Db::name('order_parent')
                ->where('order_sn',$order_sn)
                ->field('id,uid,order_sn,uid,order_price,status,create_time')
                ->find();
            if(!$order){
                throw new UserException('无此订单');
            }

            if($order['status']==-1){
                throw new UserException('订单已取消');
            }

            if($order['status']!=0){
                throw new UserException('订单已支付请勿重复支付');
            }

            if($order['order_price']!=$order_price){
                throw new UserException('订单金额不一致');
            }
        }

        //当前时间
        $time = time();
        $pay_time = empty($pay_time) ? $time : $pay_time;

        //数据变更
        $change = [
            'status'=>1,
            'pay_type'=>$pay_type,
            'is_mini_pay'=>$is_mini_pay,
            'pay_price'=>$pay_price,
            'pay_time'=>$pay_time,
            'transaction_id'=>$transaction_id
        ];

        $save = Db::name('order_parent')
            ->where('id',$order['id'])
            ->update($change);
        if(!$save){
            throw new ServerException('订单支付保存失败');
        }

        //子订单保存
        $table = config('database.connections.mysql.prefix') . 'order';
        $sql = "UPDATE ".$table." SET `status`=1,`pay_type`='".$pay_type."',`is_mini_pay`='".$is_mini_pay."',`pay_price`=order_price,`pay_time`='".$pay_time."',`transaction_id`='".$transaction_id
            ."' WHERE order_parent_id = '".$order['id']."' AND status = '0'";
        $update = Db::execute($sql);
        if(!$update){
            throw new ServerException('子订单支付保存失败');
        }

        //团购订单 过期设置按支付时间顺延的 修改过期时间
        $sql = "UPDATE ".$table." SET `expire_time`='".time()."'+(`expire_day`*86400)"
            ." WHERE order_parent_id = '".$order['id']."' AND type = '1' AND is_expire = 2";
        Db::execute($sql);

        //团购订单 有过期的修改 提醒过期时间
        $sql = "UPDATE ".$table." SET `expire_notice_time`=`expire_time`-(`expire_notice_time`*86400)"
            ." WHERE order_parent_id = '".$order['id']."' AND type = '1' AND is_expire > 0";
        Db::execute($sql);

        //购买数量
        $goods = Db::name('order_goods')
            ->where('order_parent_id','=',$order['id'])
            ->field('order_id,merch_id,goods_id,title,thumb,short_title,sku,num')
            ->select()
            ->toArray();

        $sales_arr = [];
        foreach ($goods as $go){

            $sales_arr[] = [
                'id' => $go['goods_id'],
                'sales' => Db::raw('sales+' . $go['num']),
                'sales_show' => Db::raw('sales_show+' . $go['num']),
            ];
        }

        //销量
        if(count($sales_arr)>0){
            $GoodsModel = new Goods();
            $GoodsModel->saveAll($sales_arr);
        }
    }

    /**
     * 子订单支付
     * @param $order_sn
     * @param $order
     * @param $pay_type
     * @param $order_price
     * @param $pay_price
     * @param string $transaction_id
     * @param string $pay_time
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function paySuccess($order_sn,$order,$pay_type,$order_price,$pay_price,$transaction_id='',$pay_time='',$is_mini_pay=0){

        //传订单号代表需要重新查询和校验订单
        if(!empty($order_sn)){
            $order = Db::name('order')
                ->where('order_sn',$order_sn)
                ->field('id,merch_id,order_sn,type,activity_type,verify_type,is_expire,expire_day,expire_time,expire_notice_time,
                uid,order_price,status,create_time')
                ->find();
            if(!$order){
                throw new UserException('无此购买订单');
            }

            if($order['status']==-1){
                throw new UserException('订单已取消');
            }

            if($order['status']!=0){
                throw new UserException('订单已支付请勿重复支付');
            }

            if($order['order_price']!=$order_price){
                throw new UserException('订单金额不一致');
            }
        }

        //当前时间
        $time = time();
        $pay_time = empty($pay_time) ? $time : $pay_time;

        //数据变更
        $change = [
            'status'=>1,
            'pay_type'=>$pay_type,
            'is_mini_pay'=>$is_mini_pay,
            'pay_price'=>$pay_price,
            'pay_time'=>$pay_time,
            'transaction_id'=>$transaction_id
        ];

        if($order['type']==1){
            if($order['is_expire']==1){
                $change['expire_notice_time'] = $order['expire_time']-($order['expire_notice_time']*86400);
            }elseif ($order['is_expire']==2){
                $expire_time = $time+($order['expire_day']*86400);
                $change['expire_time'] = $expire_time;
                $change['expire_notice_time'] = $expire_time-($order['expire_notice_time']*86400);
            }
        }

        $save = Db::name('order')
            ->where('id',$order['id'])
            ->update($change);
        if(!$save){
            throw new ServerException('订单支付保存失败');
        }

        //销量
        $goods = Db::name('order_goods')
            ->where('order_id','=',$order['id'])
            ->field('order_id,goods_id,title,thumb,short_title,sku,num')
            ->select()
            ->toArray();

        $sales_arr = [];
        foreach ($goods as $go){
            $sales_arr[] = [
                'id' => $go['goods_id'],
                'sales' => Db::raw('sales+' . $go['num']),
                'sales_show' => Db::raw('sales_show+' . $go['num']),
            ];
        }

        //销量
        if(count($sales_arr)>0){
            $GoodsModel = new Goods();
            $GoodsModel->saveAll($sales_arr);
        }

    }

    /**
     * 订单数量
     * @param $user
     * @param string $tag
     * @return int
     */
    static public function num($user,$tag=''){
        if(!$user){
            return 0;
        }
        $where = [
            ['uid','=',$user['id']],
            ['is_valid','=',1]
        ];

        switch ($tag){
            case 1:
                //待付款
                $where[] = ['status','=',0];
                break;
            case 2:
                //待发货 已支付未发货的好物订单
                $where[] = ['status','=',1];
                $where[] = ['type','=',2];
                break;
            case 3:
                //待核销 已支付的团购订单
                $where[] = ['status','=',1];
                $where[] = ['type','=',1];
                break;
            case 4:
                //待收货
                $where[] = ['status','=',2];
                break;
            case 5:
                //待评价
                $where[] = ['status','=',3];
                $where[] = ['comment_status','=',0];
                break;
            case 6:
                //退款 申请退款 或 已退款
                $where[] = ['status','<=',-2];
                break;
            default:
                //全部订单
        }

        $count = self::where($where)->count();
        return $count;
    }

    /**
     * 订单列表
     * @param $user
     * @param string $tag
     * @param int $page
     * @param int $page_size
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function lists($user,$tag='',$page=1,$page_size=10){
        $where = [
            ['uid','=',$user['id']],
            ['is_valid','=',1]
        ];

        switch ($tag){
            case 1:
                //待付款
                $where[] = ['status','=',0];
                break;
            case 2:
                //待发货 已支付未发货的好物订单
                $where[] = ['status','=',1];
                $where[] = ['type','=',2];
                break;
            case 3:
                //待核销 已支付的团购订单
                $where[] = ['status','=',1];
                $where[] = ['type','=',1];
                break;
            case 4:
                //待收货订单
                $where[] = ['status','=',2];
                break;
            case 5:
                //待评价 已收货或核销的 未评价的
                $where[] = ['status','=',3];
                $where[] = ['comment_status','=',0];
                break;
            case 6:
                //退款/售后 申请退款 或 已退款 或 换货的
                $where[] = ['status','<=',-2];
                break;
            case 7:
                //已完成 已收货或核销的 并且已评价的
                $where[] = ['status','=',3];
                $where[] = ['comment_status','=',1];
                break;
            default:
                //全部订单 退款的独立了
                break;
        }

        $list = self::where($where)
            ->field("id,type,activity_type,old_status,status,comment_status,goods_num,order_price,merch_id,is_change")
            ->order('id DESC')
            ->page(intval($page),intval($page_size))
            ->select()
            ->toArray();

        $coin_title = config('self.user_coin_title');
        foreach ($list as &$item){

            $merch = Merch::getInfo($item['merch_id']);
            $item['merch_title'] = $merch['title'];
            $item['merch_type'] = $merch['type'];

            $status = self::showStatusStr($item);
            $item['status_str'] = $status['str'];
            $item['status_str_color'] =  $status['color'];

            //订单的操作
            $item['btn'] = self::showController($item);

            $item['order_goods'] = Db::name('order_goods')
                ->where('order_id','=',$item['id'])
                ->field('type,activity_type,goods_id,title,thumb,price,spec_item_title,num')
                ->select()
                ->each(function ($go)use($coin_title){
                    if($go['activity_type']==2){
                        $go['price'] = ($go['price']+0).$coin_title;
                    }else{
                        $go['price'] = '￥'.($go['price']+0);
                    }

                    $go['thumb'] = manageImg($go['thumb']);
                    $go['spec_item_title'] = str_replace('+','、',$go['spec_item_title']);
                    return $go;
                })
                ->toArray();

            if($item['activity_type']==2){
                $item['order_price'] = $item['order_price'].$coin_title;
            }else{
                $item['order_price'] = '￥'.$item['order_price'];
            }

            unset($item['comment_status']);
            unset($item['status']);
            unset($item['old_status']);
            unset($item['is_change']);
        }
        unset($item);

        return $list;
    }

    /**
     * 订单按钮显示
     * @param $order
     * @return array
     */
    static public function showController($order,$is_detail=false){

        //按钮类型 1取消订单 2立即支付 3删除订单 4查看物流 5确认收货 6查看券码 7去评价 8售后退款（只有退款） 9售后退换（可退款和换货）
        //按钮样式 1空心 2实心
        $data = [];

        //待付款的订单
        if($order['status']==0){
            $data[] = [
                'style_type'=>1,
                'btn_type'=>1,
                'title'=>'取消订单'
            ];
            $data[] = [
                'style_type'=>2,
                'btn_type'=>2,
                'title'=>'立即支付'
            ];
        }

        //已取消或已退款或已收货订单可以删除
        if(in_array($order['status'],[-3,-1,3])){
            $data[] = [
                'style_type'=>1,
                'btn_type'=>3,
                'title'=>'删除订单'
            ];
        }

        //售后按钮
        if(in_array($order['status'],[1,2])){
            if($order['type']==1 || $order['is_change']){
                //团购订单 或者 已经换过货了 不再允许换货
                $data[] = [
                    'style_type'=>1,
                    'btn_type'=>8,
                    'title'=>'售后退款'
                ];
            }else{
                //好物同时未换货过可以退换
                $data[] = [
                    'style_type'=>1,
                    'btn_type'=>9,
                    'title'=>'售后退换'
                ];
            }
        }

        //好物订单查看物流
        if(!$is_detail && $order['type']==2 && (in_array($order['status'],[2,3]) || in_array($order['old_status'],[2,3]))){
            $data[] = [
                'style_type'=>1,
                'btn_type'=>4,
                'title'=>'查看物流'
            ];
        }

        //好物订单确认收货
        if($order['type']==2 && $order['status']==2){
            $data[] = [
                'style_type'=>2,
                'btn_type'=>5,
                'title'=>'确认收货'
            ];
        }

        //团购订单查看券码
        if($order['type']==1 && in_array($order['status'],[1,2])){
            $data[] = [
                'style_type'=>2,
                'btn_type'=>6,
                'title'=>'查看券码'
            ];
        }

        //评价
        if($order['status']==3 && $order['comment_status']==0){
            $data[] = [
                'style_type'=>2,
                'btn_type'=>7,
                'title'=>'去评价'
            ];
        }

        return $data;
    }

    /**
     * 前端订单状态字符串
     * @param $order
     * @return string[]
     */
    static public function showStatusStr($order){
        $coin_title = config('self.user_coin_title');

        switch ($order['status']){
            case -4:
                $str = '换货中';
                $color = '#FEC23E';
                $top_str = '您已申请了换货，请等待商家处理';
                break;
            case -3:
                $str = '已退款';
                $color = '#999999';
                $top_str = '';
                if(isset($order['refund_money'])){
                    if($order['activity_type']==2){
                        $top_str = '退款成功，退款金额'.$order['refund_money'].$coin_title;
                    }else{
                        $top_str = '退款成功，退款金额￥'.$order['refund_money'];
                    }
                }
                break;
            case -2:
                $str = '退款中';
                $color = '#FEC23E';
                $top_str = '';
                if(isset($order['refund_money'])){
                    if($order['activity_type']==2){
                        $top_str = '申请退款中，退款金额'.$order['refund_money'].$coin_title;
                    }else{
                        $top_str = '申请退款中，退款金额￥'.$order['refund_money'];
                    }
                }
                break;
            case -1:
                $str = '已取消';
                $color = '#999999';
                $top_str = '交易已取消';
                break;
            case 0:
                $str = '待付款';
                $color = '#FEC23E';
                $top_str = '';
                break;
            case 1:
                if($order['type']==1){
                    //团购
                    $str = '待使用';
                    $top_str = '';
                    if(isset($order['is_expire'])){
                        if($order['is_expire']==0){
                            $top_str = '订单长期有效，请到店出示券码使用';
                        }else{
                            $top_str = '订单'.toDate($order['expire_time'],'Y-m-d').'日到期，到期订单将自动退款';
                        }
                    }
                }else{
                    $str = '待发货';
                    $top_str = '您的订单正在出库请耐心等待';
                }

                $color = '#FEC23E';


                break;
            case 2:
                $str = '待收货';
                $color = '#FEC23E';
                $top_str = '您的订单正在路上，预计很快会送达';
                break;
            case 3:
                if($order['comment_status']){
                    //已经评价
                    $str = '已完成';
                    $color = '#999999';
                    $top_str = '交易已完成';
                }else{
                    $str = '待评价';
                    $color = '#FEC23E';
                    $top_str = '';
                }
                break;
            default:
                $str = '未知';
                $top_str = '未知';
                $color = '#999999';
        }
        return [
            'str'=>$str,
            'color'=>$color,
            'top_str'=>$top_str,
        ];
    }

    /**
     * 取消订单
     * @param $uid
     * @param $order_id
     * @return bool
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function cancel($uid,$order_id){
        $order_id = intval($order_id);

        $order = self::where('id','=',$order_id)
            ->where('uid','=',$uid)
            ->field('id,order_sn,uid,activity_type,coin,status')
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if($order['status']==-1){
            //已经取消
            return true;
        }

        if($order['status']!=0){
            throw new UserException('订单已支付，不可取消');
        }

        //订单状态
        $change = [
            'status'=>-1,
            'cancel_time'=>time()
        ];

        $save = Db::name('order')
            ->where('id','=',$order_id)
            ->where('status','=',0)
            ->update($change);
        if(!$save){
            throw new UserException('订单已取消，请勿重复操作');
        }

        //退积分
        if($order['coin']>0){
            Finance::addDelUserCoin($uid,$order['coin'],1,"订单{$order['order_sn']}取消返还",5,$order_id);
        }

        //取消订单 下单减库存的返还库存
        $goods = Db::name('order_goods')
            ->where('order_id','=',$order['id'])
            ->field('goods_id,sku,num')
            ->select()
            ->toArray();

        foreach ($goods as $go){
            Goods::where('id',$go['goods_id'])->inc('stock',$go['num'])->update();
            if($go['sku']!=''){
                Db::name('goods_spec_option')
                    ->where('goods_id','=',$go['goods_id'])
                    ->where('sku','=',trim($go['sku']))
                    ->inc('stock',$go['num'])
                    ->update();
            }
        }

        return true;
    }

    /**
     * 重新付款页面信息
     * @param $user
     * @param $order_id
     * @return array
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function payPage($user,$order_id,$source){
        $order_id = intval($order_id);

        $order = self::where('id','=',$order_id)
            ->where('uid','=',$user['id'])
            ->field('id,order_sn,order_price,type,activity_type')
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        return [
            'order_sn'=>$order['order_sn'],
            'type'=>$order['type'],
            'activity_type'=>$order['activity_type'],
            'order_price'=>$order['order_price']+0,
            'price_unit'=>$order['activity_type'] == 2 ? config('self.user_coin_title') : '￥',
            'pay_type'=>OrderNew::payList($order['activity_type'],$source),
            'tmplIds'=>MiniMsg::noticeTpl()
        ];
    }

    /**
     * 前端订单删除
     * @param $user
     * @param $order_id
     * @return true|void
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function orderAppRemove($user,$order_id){
        $order_id = intval($order_id);

        $where = [
            ['id','=',$order_id],
            ['uid','=',$user['id']]
        ];

        $order = self::where($where)
            ->field('id,status,is_valid')
            ->find();

        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if($order['is_valid']==0){
            return true;
        }

        if(!in_array($order['status'],[-1,-3,3])){
            throw new UserException('此订单不可删除');
        }

        //数据变更
        $change = [
            'is_valid'=>0,
        ];
        $save = self::where('id','=',$order_id)
            ->update($change);
        if(!$save){
            throw new ServerException('订单状态保存失败');
        }
    }

    /**
     * 展示核销码等信息
     * @param $user
     * @param $order_id
     * @return array
     * @throws ServerException
     * @throws UserException
     * @throws \Throwable
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function verifyCode($user,$order_id){
        $order_id = intval($order_id);

        //订单
        $order = self::where('id','=',$order_id)
            ->where('uid','=',$user['id'])
            ->field('id,type,verify_type,is_expire,expire_time,expire_day,
            status,verify_code')
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if($order['type']!=1){
            throw new UserException(get_base_type(3,$order['type']).'订单无核销码');
        }

        if($order['status']==0){
            throw new UserException('订单还未支付');
        }

        if($order['status']==-1){
            throw new UserException('订单已取消');
        }

        //小程序
        $path = 'https://'.config('self.official_version_domain').'/verify?id='.$order_id.'&verify_code='.$order['verify_code'];

        $code = MakeQrCode::getCode($path);

        //返回信息
        return [
            'code_img'=>$code,
            'verify_code'=>$order['verify_code']
        ];

    }

    /**
     * 确认收货
     * @param $user
     * @param $order_id
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function confirmReceive($order_id, $user=false){
        $order_id = intval($order_id);

        $where = [
            ['id','=',$order_id]
        ];
        if($user){
            $where[] = ['uid','=',$user['id']];
        }

        $order = self::where($where)
            ->find();

        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if($order['type']!=2){
            throw new UserException(get_base_type(3,$order['type']).'订单，请到店核销');
        }

        if($order['status']!= 2){
            throw new UserException('订单非待收货状态，无法确认收货');
        }

        //数据变更
        $change = [
            'status'=>3,
            'receive_time'=>time()
        ];
        $save = self::where('id','=',$order_id)
            ->where('status','=',2)
            ->update($change);
        if(!$save){
            throw new ServerException('订单状态保存失败');
        }

        //订单结算
        self::orderSettle($order);
    }

    /**
     * 订单结算
     * @param $order
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function orderSettle($order)
    {

        //商家结算
        if ($order['merch_price'] > 0) {
            Finance::addDelMerchMoney($order['merch_id'], $order['merch_price'], 1, '订单' . $order['order_sn'] . '完成结算', 4, $order['id']);
        }

        //购物给买家积分
        if($order['coin_send']>0){
            Finance::addDelUserCoin($order['uid'], $order['coin_send'], 1, "订单【{$order['order_sn']}】奖励", 7, $order['id']);
        }

        $users = Users::cacheNick($order['uid']);

        //直推奖
        if ($order['direct_price'] > 0 && $order['direct_id'] > 0) {
            Finance::addDelUserMoney($order['direct_id'], $order['direct_price'], 1, "直推【{$users['nickname']}】购物奖励", 9, $order['id']);
        }

        //团队奖
        if ($order['team2_price'] > 0 && $order['team2_id'] > 0) {
            Finance::addDelUserMoney($order['team2_id'], $order['team2_price'], 1, "团队中【{$users['nickname']}】购物奖励", 10, $order['id']);
        }

        if ($order['team3_price'] > 0 && $order['team3_id'] > 0) {
            Finance::addDelUserMoney($order['team3_id'], $order['team3_price'], 1, "团队中【{$users['nickname']}】购物奖励", 10, $order['id']);
        }

        if ($order['team4_price'] > 0 && $order['team4_id'] > 0) {
            Finance::addDelUserMoney($order['team4_id'], $order['team4_price'], 1, "团队中【{$users['nickname']}】购物奖励", 10, $order['id']);
        }

        //小区经理
        if($order['agent1_price']>0 && $order['agent1_id']>0){
            Finance::addDelAgentMoney($order['agent1_id'],$order['agent1_price'],1,"辖区订单【{$order['order_sn']}】完成奖励",4,$order['id']);
        }

        //大区经理
        if($order['agent2_price']>0 && $order['agent2_id']>0){
            Finance::addDelAgentMoney($order['agent2_id'],$order['agent2_price'],1,"辖区订单【{$order['order_sn']}】完成奖励",4,$order['id']);
        }
    }

    /**
     * 自动收货
     * @param $limit
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function autoReceive($limit){
        $auto_receive_day = Settings::getSystem('auto_receive_day');
        $time = $auto_receive_day*86400;
        $time = time()-$time;//发货时间小于此时间即到期

        $list = self::where('type','=',2)
            ->where('status','=',2)
            ->where('send_time','<',$time)
            ->limit($limit)
            ->order('id ASC')
            ->select()
            ->toArray();
        foreach ($list as $order){

            //数据变更
            $change = [
                'status'=>3,
                'receive_time'=>time()
            ];
            $save = self::where('id','=',$order['id'])
                ->where('status','=',2)
                ->update($change);

            if($save){
                //订单结算
                self::orderSettle($order);
            }

        }
    }

    /**
     * 订单详情
     * @param $user
     * @param $order_id
     * @return array
     * @throws DeveloperException
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function detail($user,$order_id,$longitude,$latitude){
        $order_id = intval($order_id);

        $where = [
            ['id','=',$order_id],
            ['uid','=',$user['id']]
        ];

        $order = Db::name('order')
            ->where($where)
            ->find();

        if(!$order){
            throw new UserException('无此订单或无权查看');
        }

        if($order['is_valid']==0){
            throw new UserException('订单已删除');
        }

        //状态
        $status = self::showStatusStr($order);

        //是否显示查看物流
        $show_express = 0;
        if($order['type']==2 && (in_array($order['status'],[2,3]) || in_array($order['old_status'],[2,3]))){
            $show_express = 1;
        }

        //收货地址
        $address = [
            'name'=>$order['send_name'],
            'mobile'=>star_mobile($order['send_mobile']),
            'address'=>Region::getRegionName($order['pro_id']).Region::getRegionName($order['city_id']).Region::getRegionName($order['area_id']).$order['send_address'],
            'show_express'=>$show_express
        ];

        //商品
        $order_goods = Db::name('order_goods')
            ->where('order_id','=',$order_id)
            ->field('goods_id,type,activity_type,title,thumb,price,spec_item_title,num')
            ->select()
            ->toArray();

        $coin_title = config('self.user_coin_title');

        foreach ($order_goods as &$item){
            $item['spec_item_title'] = str_replace('+','、',$item['spec_item_title']);
            $item['thumb'] = manageImg($item['thumb']);
            if($item['activity_type']==2){
                $item['price'] = ($item['price']+0).$coin_title;
            }else{
                $item['price'] = '￥'.($item['price']+0);
            }

        }
        unset($item);

        //商家
        $merch = Merch::getInfo($order['merch_id']);

        //价格显示
        $price_arr = [];

        if($order['activity_type']!=2){
            if($order['dispatch_price']>0){
                $price_arr[] = [
                    'show_type'=>'1',
                    'title'=>'配送费',
                    'value'=>'￥'.$order['dispatch_price']
                ];
            }

            if($order['coin_deduct']>0){
                $price_arr[] = [
                    'show_type'=>'1',
                    'title'=>$coin_title.'抵扣',
                    'value'=>'-￥'.$order['coin_deduct']
                ];
            }

            $price_arr[] = [
                'show_type'=>'2',
                'title'=>'订单金额',
                'value'=>'￥'.$order['order_price']
            ];
        }else{
            $price_arr[] = [
                'show_type'=>'2',
                'title'=>'订单金额',
                'value'=>$order['order_price'].$coin_title
            ];
        }

        //显示倒计时
        $show_count_down = 0;
        $count_down = 0;
        $system = Settings::getSystem();

        if($order['status']==0){
            //待付款
            $show_count_down = 1;
            $count_down = $order['create_time'] + $system['order_over_time']*60 - time();
        }

        if($order['status']>=3 && $order['comment_status']==0){
            //待评价
            $show_count_down = 2;
            $count_down = $order['receive_time'] + $system['comment_over_day']*86400 - time();
        }

        $count_down = max($count_down,0);

        return [
            'id'=>$order_id,
            'type'=>$order['type'],
            'activity_type'=>$order['activity_type'],
            'status_str'=>$status['str'],
            'status_desc'=>$status['top_str'],
            'show_count_down'=>$show_count_down,
            'count_down'=>$count_down,
            'address'=>$address,
            'merch'=>[
                'id'=>$order['merch_id'],
                'type'=>$merch['type'],
                'title'=>$merch['title'],
                'address'=>Region::getRegionName($merch['city_id']).Region::getRegionName($merch['area_id']).$merch['address'],
                'longitude'=>$merch['longitude'],
                'latitude'=>$merch['latitude'],
                'distance'=>($longitude&&$latitude) ? ('距离'.distance($latitude,$longitude,$merch['latitude'],$merch['longitude']).'km') : ''
            ],
            'order_goods'=>$order_goods,
            'price_arr'=>$price_arr,
            'note'=>$order['note'],
            'info'=>self::showInfo($order),
            'btn' => self::showController($order,true),
        ];
    }

    static public function showInfo($order)
    {
        //展示信息
        $info = [
            [
                'title'=>'订单编号',
                'value'=>$order['order_sn']
            ],
            [
                'title' => '下单时间',
                'value' => toDate($order['create_time'])
            ]
        ];

        if ($order['status'] == -1) {
            //已取消
            array_push($info, [
                'title' => '取消时间',
                'value' => toDate($order['cancel_time'])
            ]);
        }

        if ($order['status'] > 0 || $order['status']<=-2) {
            $pay_type = get_pay_type(3,$order['pay_type']);
            array_push($info, [
                'title' => '支付方式',
                'value' => $pay_type
            ]);
            array_push($info, [
                'title' => '支付时间',
                'value' => toDate($order['pay_time'])
            ]);

        }

        if($order['status']>1 || $order['old_status']>1){
            if ($order['type']==2){
                //快递
                array_push($info, [
                    'title' => '发货时间',
                    'value' => toDate($order['send_time'])
                ]);
                array_push($info, [
                    'title' => '快递公司',
                    'value' => $order['send_express']
                ]);
                array_push($info, [
                    'title' => '快递单号',
                    'value' => $order['send_sn']
                ]);
            }
        }

        if($order['status']==-4){
            array_push($info, [
                'title' => '申请换货',
                'value' => toDate($order['change_apply_time'])
            ]);
        }

        if($order['is_change']){
            array_push($info, [
                'title' => '确认换货',
                'value' => toDate($order['change_time'])
            ]);
        }

        //自己申请退款或到期未核销完成自动退款了
        if(in_array($order['status'],[-2,-3])){
            array_push($info, [
                'title' => '申请退款',
                'value' => toDate($order['refund_apply_time'])
            ]);
            array_push($info, [
                'title' => '退款原因',
                'value' => $order['refund_reason']
            ]);

            array_push($info, [
                'title' => '退款金额',
                'value' => $order['refund_money']
            ]);
        }

        //自己申请退款或到期未核销完成自动退款了
        if ($order['status'] == -3) {
            array_push($info, [
                'title' => '退款时间',
                'value' => toDate($order['refund_time'])
            ]);

            array_push($info, [
                'title' => '退款方式',
                'value' => $order['refund_sn']=='线下退款' ? '线下退款' : '原路退款'
            ]);

        }

        if($order['type']==1 && $order['verify_type']==2){
            $num = OrderVerify::where('order_id',$order['id'])->sum('num');
            if($num>0){
                array_push($info, [
                    'title' => '累计核销',
                    'value' => $num.'次'
                ]);
            }
        }

        if($order['status']>=3){
            array_push($info, [
                'title' => '完成时间',
                'value' => toDate($order['receive_time'])
            ]);
        }

        return $info;
    }

    /**
     * 订单物流信息
     * @param $order_id
     * @param $user
     * @return array
     * @throws UserException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function expressInfo($order_id,$user=false)
    {
        $order_id = intval($order_id);
        $where = [
            ['id', '=', $order_id]
        ];
        if ($user) {
            $where[] = ['uid', '=', $user['id']];
        }

        $order = self::where($where)
            ->field('type,order_sn,status,old_status,create_time,pay_time,
            send_express_id,send_express,send_sn,
            send_time,send_address,send_mobile')
            ->find();

        if (!$order) {
            throw new UserException('无此订单记录');
        }

        if ($order['type']!=2) {
            throw new UserException('此类型无物流');
        }

        if (!in_array($order['status'],[2,3]) && !in_array($order['old_status'],[2,3])) {
            throw new UserException('订单未录入发货信息，无物流信息');
        }

        //获取物流设置
        $res = Express::info($order['send_express_id'], $order['send_sn'], $order['send_mobile']);
        if ($res['infoStatus'] == 0) {
            $list = [];
        } elseif ($res['infoStatus'] == 1) {
            $list = [
                [
                    'time' => date('Y-m-d H:i:s'),
                    'context' => @$res['message']
                ]
            ];
        } else {
            $list = $res['data'];
            foreach ($list as &$item){
                unset($item['status']);
            }
            unset($item);
        }

        if ($order['send_time']) {
            $list[] = ['time' => toDate($order['send_time']), 'context' => '您的订单发货信息已录入'];
        }
        $list[] = ['time' => toDate($order['pay_time']), 'context' => '订单付款成功'];
        $list[] = ['time' => toDate($order['create_time']), 'context' => '订单已提交，等待付款'];

        $arr = [
            'order_sn' => $order['order_sn'],
            'send_express' => $order['send_express'],
            'send_sn' => $order['send_sn'],
            'data' => $list,
        ];
        return $arr;
    }

    /**
     * 后端订单删除
     * @param $order_id
     * @param string $merch_id
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function orderDel($order_id){
        $where = [
            ['id','=',$order_id]
        ];

        $order = self::where($where)
            ->field('id,status')
            ->find();
        if(!$order){
            throw new UserException('已删除，请勿重复操作');
        }

        if($order['status']!=-1){
            throw new UserException('只能删除已取消的订单');
        }

        $del = self::destroy($order_id);
        if(!$del){
            throw new ServerException('删除失败，请稍后再试');
        }

        Db::name('order_goods')
            ->where('order_id','=',$order_id)
            ->delete();
    }

    /**
     * 后台发货
     * @param $order_id
     * @param $send_express_id
     * @param $send_sn
     * @param $send_time
     * @param $type
     * @param $merch_id
     * @return void
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function orderSend($order_id,$send_express_id,$send_sn,$send_time=false,$type=1){

        if($type==1){
            $where = [
                ['id','=',$order_id]
            ];
        }else{
            $where = [
                ['order_sn','=',$order_id]
            ];
        }

        $order = self::where($where)
            ->field('id,uid,merch_id,order_sn,type,activity_type,status,send_name,send_mobile,send_address,send_express_id,send_sn')
            ->find();

        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if(in_array($order['status'],[0,-1])){
            throw new UserException('订单未付款或已取消');
        }

        if($order['status']<=-2){
            throw new UserException('订单已申请售后');
        }

        if($order['status']>=3){
            throw new UserException('订单已完成');
        }

        if($order['type']!=2){
            throw new UserException(get_base_type(3,$order['type']).'订单只能核销不能发快递');
        }

        //快递公司
        $send_arr = Settings::getSettings(ZFN_SETTINGS_EXPRESS);
        if(!isset($send_arr[$send_express_id])){
            throw new UserException('无此快递公司');
        }
        if($send_arr[$send_express_id]['status']!=1){
            throw new UserException($send_arr[$send_express_id]['title'].'已停止使用');
        }

        //快递单号
        $send_sn = reInject($send_sn);
        if(empty($send_sn)){
            throw new UserException('请输入快递单号，避免特殊字符');
        }

        $send_time = strtotime($send_time);
        if(!$send_time){
            $send_time = time();
        }

        $change = [
            'status'=>2,
            'send_express_id'=>$send_express_id,
            'send_express'=>$send_arr[$send_express_id]['title'],
            'send_sn'=>$send_sn,
            'send_time'=>$send_time
        ];

        $save = self::where('id',$order['id'])
            ->where('status','in',[1,2])
            ->update($change);
        if(!$save){
            throw new ServerException('发货信息保存失败，请稍后再试');
        }

        //通知买家发货了
        if($order['uid']){
            $goods = Db::name('order_goods')
                ->where('order_id','=',$order_id)
                ->field('title,thumb')
                ->find();
            if($goods){
                Notice::systemSend(2,$order['uid'],'订单发货提醒',$goods['title'].'，商家已发货',3,$order['id']);
            }
        }
    }

}